﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BrainNet.NeuralFramework;
using System.Collections;
using TSL.Model;
using System.Diagnostics;

namespace TSL
{
    class Neural
    {
        private BrainNet.NeuralFramework.INeuralNetwork network;
        private Dictionary<double, string> outputDictionary;
        public double[][] INPUT;
        public double[][] IDEAL;
        private TrainingData td;
        private int outputLayer = 10;

        public void CreateNetwork()
        {
            BackPropNetworkFactory factory = new BackPropNetworkFactory();
            ArrayList layers = new ArrayList();

            // 63-52-1 Network
            layers.Add(63);
            layers.Add(52);
            layers.Add(outputLayer);

            network = factory.CreateNetwork(layers);
            td = new TrainingData();
        }

        public void CreateTrainingSet(List<Gesture> inputList)
        {
            List<double[]> inputDummyList = new List<double[]>();
            List<double[]> idealDummyList = new List<double[]>();
            outputDictionary = new Dictionary<double, string>();

            //for all input Gesture 
            foreach (Gesture g in inputList)
            {
                //if (!(outputDictionary.ContainsValue(g.GestureName) && (outputDictionary.ContainsKey(g.GestureNo))))
                //{
                //    outputDictionary.Add(g.GestureNo, g.GestureName);
                //}

                #region prepare 5 input Frames
                List<Model.Frame> allInputFrame = new List<Model.Frame>();

                Model.Frame firstFrame = g.GestureFrames[0];
                Model.Frame lastFrame = g.GestureFrames[g.TotalFrame - 1];
                Model.Frame secondFrame;
                Model.Frame middleFrame;
                Model.Frame fourthFrame;
                if ((g.TotalFrame % 2) == 0)
                {
                    #region Merge two frame into middleframe
                    Model.Frame firstMidFrame = g.GestureFrames[((g.TotalFrame / 2) - 1)];
                    Model.Frame secondMidFrame = g.GestureFrames[((g.TotalFrame / 2) + 1)];

                    //merge two frame into one
                    middleFrame = new Model.Frame();
                    JoinFrame head = new JoinFrame();
                    head.X = (firstMidFrame.Head.X + secondMidFrame.Head.X) / 2; head.Y = (firstMidFrame.Head.Y + secondMidFrame.Head.Y) / 2; head.Z = (firstMidFrame.Head.Z + secondMidFrame.Head.Z) / 2;
                    JoinFrame handLeft = new JoinFrame();
                    handLeft.X = (firstMidFrame.HandLeft.X + secondMidFrame.HandLeft.X) / 2; handLeft.Y = (firstMidFrame.HandLeft.Y + secondMidFrame.HandLeft.Y) / 2; handLeft.Z = (firstMidFrame.HandLeft.Z + secondMidFrame.HandLeft.Z) / 2;
                    JoinFrame handRight = new JoinFrame();
                    handRight.X = (firstMidFrame.HandRight.X + secondMidFrame.HandRight.X) / 2; handRight.Y = (firstMidFrame.HandRight.Y + secondMidFrame.HandRight.Y) / 2; handRight.Z = (firstMidFrame.HandRight.Z + secondMidFrame.HandRight.Z) / 2;
                    JoinFrame shoulderLeft = new JoinFrame();
                    shoulderLeft.X = (firstMidFrame.ShoulderLeft.X + secondMidFrame.ShoulderLeft.X) / 2; shoulderLeft.Y = (firstMidFrame.ShoulderLeft.Y + secondMidFrame.ShoulderLeft.Y) / 2; shoulderLeft.Z = (firstMidFrame.ShoulderLeft.Z + secondMidFrame.ShoulderLeft.Z) / 2;
                    JoinFrame shoulderRight = new JoinFrame();
                    shoulderRight.X = (firstMidFrame.ShoulderRight.X + secondMidFrame.ShoulderRight.X) / 2; shoulderRight.Y = (firstMidFrame.ShoulderRight.Y + secondMidFrame.ShoulderRight.Y) / 2; shoulderRight.Z = (firstMidFrame.ShoulderRight.Z + secondMidFrame.ShoulderRight.Z) / 2;
                    JoinFrame hipLeft = new JoinFrame();
                    hipLeft.X = (firstMidFrame.HipLeft.X + secondMidFrame.HipLeft.X) / 2; hipLeft.Y = (firstMidFrame.HipLeft.Y + secondMidFrame.HipLeft.Y) / 2; hipLeft.Z = (firstMidFrame.HipLeft.Z + secondMidFrame.HipLeft.Z) / 2;
                    JoinFrame hipRight = new JoinFrame();
                    hipRight.X = (firstMidFrame.HipRight.X + secondMidFrame.HipRight.X) / 2; hipRight.Y = (firstMidFrame.HipRight.Y + secondMidFrame.HipRight.Y) / 2; hipRight.Z = (firstMidFrame.HipRight.Z + secondMidFrame.HipRight.Z) / 2;
                    middleFrame.Head = head; middleFrame.HandLeft = handLeft; middleFrame.HandRight = handLeft;
                    middleFrame.ShoulderLeft = shoulderLeft; middleFrame.ShoulderRight = shoulderRight;
                    middleFrame.HipLeft = hipLeft; middleFrame.HipRight = hipRight;
                    middleFrame.FrameNo = 1;
                    #endregion

                    int firstLength = firstMidFrame.FrameNo - firstFrame.FrameNo;
                    int lastLength = lastFrame.FrameNo - secondMidFrame.FrameNo;

                    if ((firstLength % 2) == 0)
                    {
                        #region Merge two frame into first frame
                        Model.Frame firstNewFrame = g.GestureFrames[((firstLength / 2) - 1)];
                        Model.Frame secondNewFrame = g.GestureFrames[((firstLength / 2) + 1)];
                        //merge two frame into one
                        secondFrame = new Model.Frame();
                        head.X = (firstNewFrame.Head.X + secondNewFrame.Head.X) / 2; head.Y = (firstNewFrame.Head.Y + secondNewFrame.Head.Y) / 2; head.Z = (firstNewFrame.Head.Z + secondNewFrame.Head.Z) / 2;
                        handLeft.X = (firstNewFrame.HandLeft.X + secondNewFrame.HandLeft.X) / 2; handLeft.Y = (firstNewFrame.HandLeft.Y + secondNewFrame.HandLeft.Y) / 2; handLeft.Z = (firstNewFrame.HandLeft.Z + secondNewFrame.HandLeft.Z) / 2;
                        handRight.X = (firstNewFrame.HandRight.X + secondNewFrame.HandRight.X) / 2; handRight.Y = (firstNewFrame.HandRight.Y + secondNewFrame.HandRight.Y) / 2; handRight.Z = (firstNewFrame.HandRight.Z + secondNewFrame.HandRight.Z) / 2;
                        shoulderLeft.X = (firstNewFrame.ShoulderLeft.X + secondNewFrame.ShoulderLeft.X) / 2; shoulderLeft.Y = (firstNewFrame.ShoulderLeft.Y + secondNewFrame.ShoulderLeft.Y) / 2; shoulderLeft.Z = (firstNewFrame.ShoulderLeft.Z + secondNewFrame.ShoulderLeft.Z) / 2;
                        shoulderRight.X = (firstNewFrame.ShoulderRight.X + secondNewFrame.ShoulderRight.X) / 2; shoulderRight.Y = (firstNewFrame.ShoulderRight.Y + secondNewFrame.ShoulderRight.Y) / 2; shoulderRight.Z = (firstNewFrame.ShoulderRight.Z + secondNewFrame.ShoulderRight.Z) / 2;
                        hipLeft.X = (firstNewFrame.HipLeft.X + secondNewFrame.HipLeft.X) / 2; hipLeft.Y = (firstNewFrame.HipLeft.Y + secondNewFrame.HipLeft.Y) / 2; hipLeft.Z = (firstNewFrame.HipLeft.Z + secondNewFrame.HipLeft.Z) / 2;
                        hipRight.X = (firstNewFrame.HipRight.X + secondNewFrame.HipRight.X) / 2; hipRight.Y = (firstNewFrame.HipRight.Y + secondNewFrame.HipRight.Y) / 2; hipRight.Z = (firstNewFrame.HipRight.Z + secondNewFrame.HipRight.Z) / 2;
                        secondFrame.Head = head; secondFrame.HandLeft = handLeft; secondFrame.HandRight = handLeft;
                        secondFrame.ShoulderLeft = shoulderLeft; secondFrame.ShoulderRight = shoulderRight;
                        secondFrame.HipLeft = hipLeft; secondFrame.HipRight = hipRight;
                        secondFrame.FrameNo = 0;
                        #endregion
                    }
                    else
                    {
                        secondFrame = g.GestureFrames[(firstLength / 2)];
                    }
                    if ((lastLength % 2) == 0)
                    {
                        #region Merge two frame into last frame
                        Model.Frame firstNewFrame = g.GestureFrames[((lastLength / 2) - 1)];
                        Model.Frame secondNewFrame = g.GestureFrames[((lastLength / 2) + 1)];
                        //merge two frame into one
                        fourthFrame = new Model.Frame();
                        head.X = (firstNewFrame.Head.X + secondNewFrame.Head.X) / 2; head.Y = (firstNewFrame.Head.Y + secondNewFrame.Head.Y) / 2; head.Z = (firstNewFrame.Head.Z + secondNewFrame.Head.Z) / 2;
                        handLeft.X = (firstNewFrame.HandLeft.X + secondNewFrame.HandLeft.X) / 2; handLeft.Y = (firstNewFrame.HandLeft.Y + secondNewFrame.HandLeft.Y) / 2; handLeft.Z = (firstNewFrame.HandLeft.Z + secondNewFrame.HandLeft.Z) / 2;
                        handRight.X = (firstNewFrame.HandRight.X + secondNewFrame.HandRight.X) / 2; handRight.Y = (firstNewFrame.HandRight.Y + secondNewFrame.HandRight.Y) / 2; handRight.Z = (firstNewFrame.HandRight.Z + secondNewFrame.HandRight.Z) / 2;
                        shoulderLeft.X = (firstNewFrame.ShoulderLeft.X + secondNewFrame.ShoulderLeft.X) / 2; shoulderLeft.Y = (firstNewFrame.ShoulderLeft.Y + secondNewFrame.ShoulderLeft.Y) / 2; shoulderLeft.Z = (firstNewFrame.ShoulderLeft.Z + secondNewFrame.ShoulderLeft.Z) / 2;
                        shoulderRight.X = (firstNewFrame.ShoulderRight.X + secondNewFrame.ShoulderRight.X) / 2; shoulderRight.Y = (firstNewFrame.ShoulderRight.Y + secondNewFrame.ShoulderRight.Y) / 2; shoulderRight.Z = (firstNewFrame.ShoulderRight.Z + secondNewFrame.ShoulderRight.Z) / 2;
                        hipLeft.X = (firstNewFrame.HipLeft.X + secondNewFrame.HipLeft.X) / 2; hipLeft.Y = (firstNewFrame.HipLeft.Y + secondNewFrame.HipLeft.Y) / 2; hipLeft.Z = (firstNewFrame.HipLeft.Z + secondNewFrame.HipLeft.Z) / 2;
                        hipRight.X = (firstNewFrame.HipRight.X + secondNewFrame.HipRight.X) / 2; hipRight.Y = (firstNewFrame.HipRight.Y + secondNewFrame.HipRight.Y) / 2; hipRight.Z = (firstNewFrame.HipRight.Z + secondNewFrame.HipRight.Z) / 2;
                        fourthFrame.Head = head; fourthFrame.HandLeft = handLeft; fourthFrame.HandRight = handLeft;
                        fourthFrame.ShoulderLeft = shoulderLeft; fourthFrame.ShoulderRight = shoulderRight;
                        fourthFrame.HipLeft = hipLeft; fourthFrame.HipRight = hipRight;
                        fourthFrame.FrameNo = 2;
                        #endregion
                    }
                    else
                    {
                        fourthFrame = g.GestureFrames[secondMidFrame.FrameNo + (lastLength / 2)];
                    }
                }
                else
                {
                    middleFrame = g.GestureFrames[g.TotalFrame / 2];
                    int firstLength = middleFrame.FrameNo - firstFrame.FrameNo;
                    int lastLength = lastFrame.FrameNo - middleFrame.FrameNo;
                    if ((firstLength % 2) == 0)
                    {
                        #region Merge two frame into first frame
                        Model.Frame firstNewFrame = g.GestureFrames[((firstLength / 2) - 1)];
                        Model.Frame secondNewFrame = g.GestureFrames[((firstLength / 2) + 1)];
                        //merge two frame into one
                        secondFrame = new Model.Frame();
                        JoinFrame head = new JoinFrame();
                        head.X = (firstNewFrame.Head.X + secondNewFrame.Head.X) / 2; head.Y = (firstNewFrame.Head.Y + secondNewFrame.Head.Y) / 2; head.Z = (firstNewFrame.Head.Z + secondNewFrame.Head.Z) / 2;
                        JoinFrame handLeft = new JoinFrame();
                        handLeft.X = (firstNewFrame.HandLeft.X + secondNewFrame.HandLeft.X) / 2; handLeft.Y = (firstNewFrame.HandLeft.Y + secondNewFrame.HandLeft.Y) / 2; handLeft.Z = (firstNewFrame.HandLeft.Z + secondNewFrame.HandLeft.Z) / 2;
                        JoinFrame handRight = new JoinFrame();
                        handRight.X = (firstNewFrame.HandRight.X + secondNewFrame.HandRight.X) / 2; handRight.Y = (firstNewFrame.HandRight.Y + secondNewFrame.HandRight.Y) / 2; handRight.Z = (firstNewFrame.HandRight.Z + secondNewFrame.HandRight.Z) / 2;
                        JoinFrame shoulderLeft = new JoinFrame();
                        shoulderLeft.X = (firstNewFrame.ShoulderLeft.X + secondNewFrame.ShoulderLeft.X) / 2; shoulderLeft.Y = (firstNewFrame.ShoulderLeft.Y + secondNewFrame.ShoulderLeft.Y) / 2; shoulderLeft.Z = (firstNewFrame.ShoulderLeft.Z + secondNewFrame.ShoulderLeft.Z) / 2;
                        JoinFrame shoulderRight = new JoinFrame();
                        shoulderRight.X = (firstNewFrame.ShoulderRight.X + secondNewFrame.ShoulderRight.X) / 2; shoulderRight.Y = (firstNewFrame.ShoulderRight.Y + secondNewFrame.ShoulderRight.Y) / 2; shoulderRight.Z = (firstNewFrame.ShoulderRight.Z + secondNewFrame.ShoulderRight.Z) / 2;
                        JoinFrame hipLeft = new JoinFrame();
                        hipLeft.X = (firstNewFrame.HipLeft.X + secondNewFrame.HipLeft.X) / 2; hipLeft.Y = (firstNewFrame.HipLeft.Y + secondNewFrame.HipLeft.Y) / 2; hipLeft.Z = (firstNewFrame.HipLeft.Z + secondNewFrame.HipLeft.Z) / 2;
                        JoinFrame hipRight = new JoinFrame();
                        hipRight.X = (firstNewFrame.HipRight.X + secondNewFrame.HipRight.X) / 2; hipRight.Y = (firstNewFrame.HipRight.Y + secondNewFrame.HipRight.Y) / 2; hipRight.Z = (firstNewFrame.HipRight.Z + secondNewFrame.HipRight.Z) / 2;
                        secondFrame.Head = head; secondFrame.HandLeft = handLeft; secondFrame.HandRight = handLeft;
                        secondFrame.ShoulderLeft = shoulderLeft; secondFrame.ShoulderRight = shoulderRight;
                        secondFrame.HipLeft = hipLeft; secondFrame.HipRight = hipRight;
                        secondFrame.FrameNo = 0;
                        #endregion
                    }
                    else
                    {
                        secondFrame = g.GestureFrames[(firstLength / 2)];
                    }
                    if ((lastLength % 2) == 0)
                    {
                        #region Merge two frame into last frame
                        Model.Frame firstNewFrame = g.GestureFrames[((lastLength / 2) - 1)];
                        Model.Frame secondNewFrame = g.GestureFrames[((lastLength / 2) + 1)];
                        //merge two frame into one
                        fourthFrame = new Model.Frame();
                        JoinFrame head = new JoinFrame();
                        head.X = (firstNewFrame.Head.X + secondNewFrame.Head.X) / 2; head.Y = (firstNewFrame.Head.Y + secondNewFrame.Head.Y) / 2; head.Z = (firstNewFrame.Head.Z + secondNewFrame.Head.Z) / 2;
                        JoinFrame handLeft = new JoinFrame();
                        handLeft.X = (firstNewFrame.HandLeft.X + secondNewFrame.HandLeft.X) / 2; handLeft.Y = (firstNewFrame.HandLeft.Y + secondNewFrame.HandLeft.Y) / 2; handLeft.Z = (firstNewFrame.HandLeft.Z + secondNewFrame.HandLeft.Z) / 2;
                        JoinFrame handRight = new JoinFrame();
                        handRight.X = (firstNewFrame.HandRight.X + secondNewFrame.HandRight.X) / 2; handRight.Y = (firstNewFrame.HandRight.Y + secondNewFrame.HandRight.Y) / 2; handRight.Z = (firstNewFrame.HandRight.Z + secondNewFrame.HandRight.Z) / 2;
                        JoinFrame shoulderLeft = new JoinFrame();
                        shoulderLeft.X = (firstNewFrame.ShoulderLeft.X + secondNewFrame.ShoulderLeft.X) / 2; shoulderLeft.Y = (firstNewFrame.ShoulderLeft.Y + secondNewFrame.ShoulderLeft.Y) / 2; shoulderLeft.Z = (firstNewFrame.ShoulderLeft.Z + secondNewFrame.ShoulderLeft.Z) / 2;
                        JoinFrame shoulderRight = new JoinFrame();
                        shoulderRight.X = (firstNewFrame.ShoulderRight.X + secondNewFrame.ShoulderRight.X) / 2; shoulderRight.Y = (firstNewFrame.ShoulderRight.Y + secondNewFrame.ShoulderRight.Y) / 2; shoulderRight.Z = (firstNewFrame.ShoulderRight.Z + secondNewFrame.ShoulderRight.Z) / 2;
                        JoinFrame hipLeft = new JoinFrame();
                        hipLeft.X = (firstNewFrame.HipLeft.X + secondNewFrame.HipLeft.X) / 2; hipLeft.Y = (firstNewFrame.HipLeft.Y + secondNewFrame.HipLeft.Y) / 2; hipLeft.Z = (firstNewFrame.HipLeft.Z + secondNewFrame.HipLeft.Z) / 2;
                        JoinFrame hipRight = new JoinFrame();
                        hipRight.X = (firstNewFrame.HipRight.X + secondNewFrame.HipRight.X) / 2; hipRight.Y = (firstNewFrame.HipRight.Y + secondNewFrame.HipRight.Y) / 2; hipRight.Z = (firstNewFrame.HipRight.Z + secondNewFrame.HipRight.Z) / 2;
                        fourthFrame.Head = head; fourthFrame.HandLeft = handLeft; fourthFrame.HandRight = handLeft;
                        fourthFrame.ShoulderLeft = shoulderLeft; fourthFrame.ShoulderRight = shoulderRight;
                        fourthFrame.HipLeft = hipLeft; fourthFrame.HipRight = hipRight;
                        fourthFrame.FrameNo = 2;
                        #endregion
                    }
                    else
                    {
                        fourthFrame = g.GestureFrames[middleFrame.FrameNo + (lastLength / 2)];
                    }
                }
                //allInputFrame.Add(firstFrame);
                allInputFrame.Add(secondFrame);
                allInputFrame.Add(middleFrame);
                allInputFrame.Add(fourthFrame);
                //allInputFrame.Add(lastFrame);
                #endregion

                #region CreateinputArray
                double[] allInputNode = new double[63];
                int inputIndex = 0; int gestureIndex = 0;
                foreach (Model.Frame fr in allInputFrame)
                {
                    for (int i = 1; i <= 7; i++)
                    {
                        switch (i)
                        {
                            case 1:
                                {
                                    allInputNode[inputIndex] = fr.Head.X; inputIndex++;
                                    allInputNode[inputIndex] = fr.Head.Y; inputIndex++;
                                    allInputNode[inputIndex] = fr.Head.Z; inputIndex++;
                                    break;
                                }
                            case 2:
                                {
                                    allInputNode[inputIndex] = fr.HandLeft.X; inputIndex++;
                                    allInputNode[inputIndex] = fr.HandLeft.Y; inputIndex++;
                                    allInputNode[inputIndex] = fr.HandLeft.Z; inputIndex++;
                                    break;
                                }
                            case 3:
                                {
                                    allInputNode[inputIndex] = fr.HandRight.X; inputIndex++;
                                    allInputNode[inputIndex] = fr.HandRight.Y; inputIndex++;
                                    allInputNode[inputIndex] = fr.HandRight.Z; inputIndex++;
                                    break;
                                }
                            case 4:
                                {
                                    allInputNode[inputIndex] = fr.ShoulderLeft.X; inputIndex++;
                                    allInputNode[inputIndex] = fr.ShoulderLeft.Y; inputIndex++;
                                    allInputNode[inputIndex] = fr.ShoulderLeft.Z; inputIndex++;
                                    break;
                                }
                            case 5:
                                {
                                    allInputNode[inputIndex] = fr.ShoulderRight.X; inputIndex++;
                                    allInputNode[inputIndex] = fr.ShoulderRight.Y; inputIndex++;
                                    allInputNode[inputIndex] = fr.ShoulderRight.Z; inputIndex++;
                                    break;
                                }
                            case 6:
                                {
                                    allInputNode[inputIndex] = fr.HipLeft.X; inputIndex++;
                                    allInputNode[inputIndex] = fr.HipLeft.Y; inputIndex++;
                                    allInputNode[inputIndex] = fr.HipLeft.Z; inputIndex++;
                                    break;
                                }
                            case 7:
                                {
                                    allInputNode[inputIndex] = fr.HipRight.X; inputIndex++;
                                    allInputNode[inputIndex] = fr.HipRight.Y; inputIndex++;
                                    allInputNode[inputIndex] = fr.HipRight.Z; inputIndex++;
                                    break;
                                }
                            default:
                                break;
                        }
                    }

                    gestureIndex++;
                }
                #endregion

                String idealString = g.GestureNo;
                double[] ideal = new double[10];
                for (int i = 0; i < 10; i++)
                {
                    ideal[i] = double.Parse(idealString[i] + "");
                }
                idealDummyList.Add(ideal);

                inputDummyList.Add(allInputNode);
            }

            //Create INPUT Array
            INPUT = new double[inputDummyList.Count][];
            for (int i = 0; i < inputDummyList.Count; i++)
            {
                INPUT[i] = inputDummyList[i];
            }

            //Create IDEAL Array
            IDEAL = new double[idealDummyList.Count][];
            for (int j = 0; j < idealDummyList.Count; j++)
            {
                IDEAL[j] = idealDummyList[j];
            }
        }

        public void CreateTrainingData(double[] inputs, double[] ideal)
        {
            td = new TrainingData();
            foreach (double d in inputs)
            {
                td.Inputs.Add(d);
            }

            foreach (double d in ideal)
            {
                td.Outputs.Add(d);
            }
            network.TrainNetwork(td);
        }

        public void StartTrain(long trainTime)
        {
            NetworkHelper helper = new NetworkHelper(network);
            for (int i = 0; i < INPUT.Length; i++)
            {
                td = new TrainingData();
                double[] l = INPUT[i];
                System.Collections.ArrayList inputs = new System.Collections.ArrayList();
                foreach (double d in l)
                {
                    //inputs.Add(d);
                    td.Inputs.Add(d);
                }
                System.Collections.ArrayList outputs = new System.Collections.ArrayList();
                foreach (double d in IDEAL[i])
                {
                    //outputs.Add(d);
                    td.Outputs.Add(d);
                }
                //helper.AddTrainingData(inputs, outputs);
                helper.AddTrainingData(td);
            }
            helper.Train(trainTime);

            //for (int time = 0; time < trainTime; time++)
            //{
            //    for (int i = 0; i < INPUT.Length; i++)
            //    {
            //        double[] l = INPUT[i];
            //        double[] ideal = IDEAL[i];
            //        CreateTrainingData(INPUT[i], IDEAL[i]);
            //    }
            //}
        }

        public ArrayList Run(Gesture testingGesture)
        {
            #region prepare 5 input Frames
            List<Model.Frame> allInputFrame = new List<Model.Frame>();

            Model.Frame firstFrame = testingGesture.GestureFrames[0];
            Model.Frame lastFrame = testingGesture.GestureFrames[testingGesture.TotalFrame - 1];
            Model.Frame secondFrame;
            Model.Frame middleFrame;
            Model.Frame fourthFrame;
            if ((testingGesture.TotalFrame % 2) == 0)
            {
                #region Merge two frame into middleframe
                Model.Frame firstMidFrame = testingGesture.GestureFrames[((testingGesture.TotalFrame / 2) - 1)];
                Model.Frame secondMidFrame = testingGesture.GestureFrames[((testingGesture.TotalFrame / 2) + 1)];

                //merge two frame into one
                middleFrame = new Model.Frame();
                JoinFrame head = new JoinFrame();
                head.X = (firstMidFrame.Head.X + secondMidFrame.Head.X) / 2; head.Y = (firstMidFrame.Head.Y + secondMidFrame.Head.Y) / 2; head.Z = (firstMidFrame.Head.Z + secondMidFrame.Head.Z) / 2;
                JoinFrame handLeft = new JoinFrame();
                handLeft.X = (firstMidFrame.HandLeft.X + secondMidFrame.HandLeft.X) / 2; handLeft.Y = (firstMidFrame.HandLeft.Y + secondMidFrame.HandLeft.Y) / 2; handLeft.Z = (firstMidFrame.HandLeft.Z + secondMidFrame.HandLeft.Z) / 2;
                JoinFrame handRight = new JoinFrame();
                handRight.X = (firstMidFrame.HandRight.X + secondMidFrame.HandRight.X) / 2; handRight.Y = (firstMidFrame.HandRight.Y + secondMidFrame.HandRight.Y) / 2; handRight.Z = (firstMidFrame.HandRight.Z + secondMidFrame.HandRight.Z) / 2;
                JoinFrame shoulderLeft = new JoinFrame();
                shoulderLeft.X = (firstMidFrame.ShoulderLeft.X + secondMidFrame.ShoulderLeft.X) / 2; shoulderLeft.Y = (firstMidFrame.ShoulderLeft.Y + secondMidFrame.ShoulderLeft.Y) / 2; shoulderLeft.Z = (firstMidFrame.ShoulderLeft.Z + secondMidFrame.ShoulderLeft.Z) / 2;
                JoinFrame shoulderRight = new JoinFrame();
                shoulderRight.X = (firstMidFrame.ShoulderRight.X + secondMidFrame.ShoulderRight.X) / 2; shoulderRight.Y = (firstMidFrame.ShoulderRight.Y + secondMidFrame.ShoulderRight.Y) / 2; shoulderRight.Z = (firstMidFrame.ShoulderRight.Z + secondMidFrame.ShoulderRight.Z) / 2;
                JoinFrame hipLeft = new JoinFrame();
                hipLeft.X = (firstMidFrame.HipLeft.X + secondMidFrame.HipLeft.X) / 2; hipLeft.Y = (firstMidFrame.HipLeft.Y + secondMidFrame.HipLeft.Y) / 2; hipLeft.Z = (firstMidFrame.HipLeft.Z + secondMidFrame.HipLeft.Z) / 2;
                JoinFrame hipRight = new JoinFrame();
                hipRight.X = (firstMidFrame.HipRight.X + secondMidFrame.HipRight.X) / 2; hipRight.Y = (firstMidFrame.HipRight.Y + secondMidFrame.HipRight.Y) / 2; hipRight.Z = (firstMidFrame.HipRight.Z + secondMidFrame.HipRight.Z) / 2;
                middleFrame.Head = head; middleFrame.HandLeft = handLeft; middleFrame.HandRight = handLeft;
                middleFrame.ShoulderLeft = shoulderLeft; middleFrame.ShoulderRight = shoulderRight;
                middleFrame.HipLeft = hipLeft; middleFrame.HipRight = hipRight;
                middleFrame.FrameNo = 1;
                #endregion

                int firstLength = firstMidFrame.FrameNo - firstFrame.FrameNo;
                int lastLength = lastFrame.FrameNo - secondMidFrame.FrameNo;

                if ((firstLength % 2) == 0)
                {
                    #region Merge two frame into first frame
                    Model.Frame firstNewFrame = testingGesture.GestureFrames[((firstLength / 2) - 1)];
                    Model.Frame secondNewFrame = testingGesture.GestureFrames[((firstLength / 2) + 1)];
                    //merge two frame into one
                    secondFrame = new Model.Frame();
                    head.X = (firstNewFrame.Head.X + secondNewFrame.Head.X) / 2; head.Y = (firstNewFrame.Head.Y + secondNewFrame.Head.Y) / 2; head.Z = (firstNewFrame.Head.Z + secondNewFrame.Head.Z) / 2;
                    handLeft.X = (firstNewFrame.HandLeft.X + secondNewFrame.HandLeft.X) / 2; handLeft.Y = (firstNewFrame.HandLeft.Y + secondNewFrame.HandLeft.Y) / 2; handLeft.Z = (firstNewFrame.HandLeft.Z + secondNewFrame.HandLeft.Z) / 2;
                    handRight.X = (firstNewFrame.HandRight.X + secondNewFrame.HandRight.X) / 2; handRight.Y = (firstNewFrame.HandRight.Y + secondNewFrame.HandRight.Y) / 2; handRight.Z = (firstNewFrame.HandRight.Z + secondNewFrame.HandRight.Z) / 2;
                    shoulderLeft.X = (firstNewFrame.ShoulderLeft.X + secondNewFrame.ShoulderLeft.X) / 2; shoulderLeft.Y = (firstNewFrame.ShoulderLeft.Y + secondNewFrame.ShoulderLeft.Y) / 2; shoulderLeft.Z = (firstNewFrame.ShoulderLeft.Z + secondNewFrame.ShoulderLeft.Z) / 2;
                    shoulderRight.X = (firstNewFrame.ShoulderRight.X + secondNewFrame.ShoulderRight.X) / 2; shoulderRight.Y = (firstNewFrame.ShoulderRight.Y + secondNewFrame.ShoulderRight.Y) / 2; shoulderRight.Z = (firstNewFrame.ShoulderRight.Z + secondNewFrame.ShoulderRight.Z) / 2;
                    hipLeft.X = (firstNewFrame.HipLeft.X + secondNewFrame.HipLeft.X) / 2; hipLeft.Y = (firstNewFrame.HipLeft.Y + secondNewFrame.HipLeft.Y) / 2; hipLeft.Z = (firstNewFrame.HipLeft.Z + secondNewFrame.HipLeft.Z) / 2;
                    hipRight.X = (firstNewFrame.HipRight.X + secondNewFrame.HipRight.X) / 2; hipRight.Y = (firstNewFrame.HipRight.Y + secondNewFrame.HipRight.Y) / 2; hipRight.Z = (firstNewFrame.HipRight.Z + secondNewFrame.HipRight.Z) / 2;
                    secondFrame.Head = head; secondFrame.HandLeft = handLeft; secondFrame.HandRight = handLeft;
                    secondFrame.ShoulderLeft = shoulderLeft; secondFrame.ShoulderRight = shoulderRight;
                    secondFrame.HipLeft = hipLeft; secondFrame.HipRight = hipRight;
                    secondFrame.FrameNo = 0;
                    #endregion
                }
                else
                {
                    secondFrame = testingGesture.GestureFrames[(firstLength / 2)];
                }
                if ((lastLength % 2) == 0)
                {
                    #region Merge two frame into last frame
                    Model.Frame firstNewFrame = testingGesture.GestureFrames[((lastLength / 2) - 1)];
                    Model.Frame secondNewFrame = testingGesture.GestureFrames[((lastLength / 2) + 1)];
                    //merge two frame into one
                    fourthFrame = new Model.Frame();
                    head.X = (firstNewFrame.Head.X + secondNewFrame.Head.X) / 2; head.Y = (firstNewFrame.Head.Y + secondNewFrame.Head.Y) / 2; head.Z = (firstNewFrame.Head.Z + secondNewFrame.Head.Z) / 2;
                    handLeft.X = (firstNewFrame.HandLeft.X + secondNewFrame.HandLeft.X) / 2; handLeft.Y = (firstNewFrame.HandLeft.Y + secondNewFrame.HandLeft.Y) / 2; handLeft.Z = (firstNewFrame.HandLeft.Z + secondNewFrame.HandLeft.Z) / 2;
                    handRight.X = (firstNewFrame.HandRight.X + secondNewFrame.HandRight.X) / 2; handRight.Y = (firstNewFrame.HandRight.Y + secondNewFrame.HandRight.Y) / 2; handRight.Z = (firstNewFrame.HandRight.Z + secondNewFrame.HandRight.Z) / 2;
                    shoulderLeft.X = (firstNewFrame.ShoulderLeft.X + secondNewFrame.ShoulderLeft.X) / 2; shoulderLeft.Y = (firstNewFrame.ShoulderLeft.Y + secondNewFrame.ShoulderLeft.Y) / 2; shoulderLeft.Z = (firstNewFrame.ShoulderLeft.Z + secondNewFrame.ShoulderLeft.Z) / 2;
                    shoulderRight.X = (firstNewFrame.ShoulderRight.X + secondNewFrame.ShoulderRight.X) / 2; shoulderRight.Y = (firstNewFrame.ShoulderRight.Y + secondNewFrame.ShoulderRight.Y) / 2; shoulderRight.Z = (firstNewFrame.ShoulderRight.Z + secondNewFrame.ShoulderRight.Z) / 2;
                    hipLeft.X = (firstNewFrame.HipLeft.X + secondNewFrame.HipLeft.X) / 2; hipLeft.Y = (firstNewFrame.HipLeft.Y + secondNewFrame.HipLeft.Y) / 2; hipLeft.Z = (firstNewFrame.HipLeft.Z + secondNewFrame.HipLeft.Z) / 2;
                    hipRight.X = (firstNewFrame.HipRight.X + secondNewFrame.HipRight.X) / 2; hipRight.Y = (firstNewFrame.HipRight.Y + secondNewFrame.HipRight.Y) / 2; hipRight.Z = (firstNewFrame.HipRight.Z + secondNewFrame.HipRight.Z) / 2;
                    fourthFrame.Head = head; fourthFrame.HandLeft = handLeft; fourthFrame.HandRight = handLeft;
                    fourthFrame.ShoulderLeft = shoulderLeft; fourthFrame.ShoulderRight = shoulderRight;
                    fourthFrame.HipLeft = hipLeft; fourthFrame.HipRight = hipRight;
                    fourthFrame.FrameNo = 2;
                    #endregion
                }
                else
                {
                    fourthFrame = testingGesture.GestureFrames[secondMidFrame.FrameNo + (lastLength / 2)];
                }
            }
            else
            {
                middleFrame = testingGesture.GestureFrames[testingGesture.TotalFrame / 2];
                int firstLength = middleFrame.FrameNo - firstFrame.FrameNo;
                int lastLength = lastFrame.FrameNo - middleFrame.FrameNo;
                if ((firstLength % 2) == 0)
                {
                    #region Merge two frame into first frame
                    Model.Frame firstNewFrame = testingGesture.GestureFrames[((firstLength / 2) - 1)];
                    Model.Frame secondNewFrame = testingGesture.GestureFrames[((firstLength / 2) + 1)];
                    //merge two frame into one
                    secondFrame = new Model.Frame();
                    JoinFrame head = new JoinFrame();
                    head.X = (firstNewFrame.Head.X + secondNewFrame.Head.X) / 2; head.Y = (firstNewFrame.Head.Y + secondNewFrame.Head.Y) / 2; head.Z = (firstNewFrame.Head.Z + secondNewFrame.Head.Z) / 2;
                    JoinFrame handLeft = new JoinFrame();
                    handLeft.X = (firstNewFrame.HandLeft.X + secondNewFrame.HandLeft.X) / 2; handLeft.Y = (firstNewFrame.HandLeft.Y + secondNewFrame.HandLeft.Y) / 2; handLeft.Z = (firstNewFrame.HandLeft.Z + secondNewFrame.HandLeft.Z) / 2;
                    JoinFrame handRight = new JoinFrame();
                    handRight.X = (firstNewFrame.HandRight.X + secondNewFrame.HandRight.X) / 2; handRight.Y = (firstNewFrame.HandRight.Y + secondNewFrame.HandRight.Y) / 2; handRight.Z = (firstNewFrame.HandRight.Z + secondNewFrame.HandRight.Z) / 2;
                    JoinFrame shoulderLeft = new JoinFrame();
                    shoulderLeft.X = (firstNewFrame.ShoulderLeft.X + secondNewFrame.ShoulderLeft.X) / 2; shoulderLeft.Y = (firstNewFrame.ShoulderLeft.Y + secondNewFrame.ShoulderLeft.Y) / 2; shoulderLeft.Z = (firstNewFrame.ShoulderLeft.Z + secondNewFrame.ShoulderLeft.Z) / 2;
                    JoinFrame shoulderRight = new JoinFrame();
                    shoulderRight.X = (firstNewFrame.ShoulderRight.X + secondNewFrame.ShoulderRight.X) / 2; shoulderRight.Y = (firstNewFrame.ShoulderRight.Y + secondNewFrame.ShoulderRight.Y) / 2; shoulderRight.Z = (firstNewFrame.ShoulderRight.Z + secondNewFrame.ShoulderRight.Z) / 2;
                    JoinFrame hipLeft = new JoinFrame();
                    hipLeft.X = (firstNewFrame.HipLeft.X + secondNewFrame.HipLeft.X) / 2; hipLeft.Y = (firstNewFrame.HipLeft.Y + secondNewFrame.HipLeft.Y) / 2; hipLeft.Z = (firstNewFrame.HipLeft.Z + secondNewFrame.HipLeft.Z) / 2;
                    JoinFrame hipRight = new JoinFrame();
                    hipRight.X = (firstNewFrame.HipRight.X + secondNewFrame.HipRight.X) / 2; hipRight.Y = (firstNewFrame.HipRight.Y + secondNewFrame.HipRight.Y) / 2; hipRight.Z = (firstNewFrame.HipRight.Z + secondNewFrame.HipRight.Z) / 2;
                    secondFrame.Head = head; secondFrame.HandLeft = handLeft; secondFrame.HandRight = handLeft;
                    secondFrame.ShoulderLeft = shoulderLeft; secondFrame.ShoulderRight = shoulderRight;
                    secondFrame.HipLeft = hipLeft; secondFrame.HipRight = hipRight;
                    secondFrame.FrameNo = 0;
                    #endregion
                }
                else
                {
                    secondFrame = testingGesture.GestureFrames[(firstLength / 2)];
                }
                if ((lastLength % 2) == 0)
                {
                    #region Merge two frame into last frame
                    Model.Frame firstNewFrame = testingGesture.GestureFrames[((lastLength / 2) - 1)];
                    Model.Frame secondNewFrame = testingGesture.GestureFrames[((lastLength / 2) + 1)];
                    //merge two frame into one
                    fourthFrame = new Model.Frame();
                    JoinFrame head = new JoinFrame();
                    head.X = (firstNewFrame.Head.X + secondNewFrame.Head.X) / 2; head.Y = (firstNewFrame.Head.Y + secondNewFrame.Head.Y) / 2; head.Z = (firstNewFrame.Head.Z + secondNewFrame.Head.Z) / 2;
                    JoinFrame handLeft = new JoinFrame();
                    handLeft.X = (firstNewFrame.HandLeft.X + secondNewFrame.HandLeft.X) / 2; handLeft.Y = (firstNewFrame.HandLeft.Y + secondNewFrame.HandLeft.Y) / 2; handLeft.Z = (firstNewFrame.HandLeft.Z + secondNewFrame.HandLeft.Z) / 2;
                    JoinFrame handRight = new JoinFrame();
                    handRight.X = (firstNewFrame.HandRight.X + secondNewFrame.HandRight.X) / 2; handRight.Y = (firstNewFrame.HandRight.Y + secondNewFrame.HandRight.Y) / 2; handRight.Z = (firstNewFrame.HandRight.Z + secondNewFrame.HandRight.Z) / 2;
                    JoinFrame shoulderLeft = new JoinFrame();
                    shoulderLeft.X = (firstNewFrame.ShoulderLeft.X + secondNewFrame.ShoulderLeft.X) / 2; shoulderLeft.Y = (firstNewFrame.ShoulderLeft.Y + secondNewFrame.ShoulderLeft.Y) / 2; shoulderLeft.Z = (firstNewFrame.ShoulderLeft.Z + secondNewFrame.ShoulderLeft.Z) / 2;
                    JoinFrame shoulderRight = new JoinFrame();
                    shoulderRight.X = (firstNewFrame.ShoulderRight.X + secondNewFrame.ShoulderRight.X) / 2; shoulderRight.Y = (firstNewFrame.ShoulderRight.Y + secondNewFrame.ShoulderRight.Y) / 2; shoulderRight.Z = (firstNewFrame.ShoulderRight.Z + secondNewFrame.ShoulderRight.Z) / 2;
                    JoinFrame hipLeft = new JoinFrame();
                    hipLeft.X = (firstNewFrame.HipLeft.X + secondNewFrame.HipLeft.X) / 2; hipLeft.Y = (firstNewFrame.HipLeft.Y + secondNewFrame.HipLeft.Y) / 2; hipLeft.Z = (firstNewFrame.HipLeft.Z + secondNewFrame.HipLeft.Z) / 2;
                    JoinFrame hipRight = new JoinFrame();
                    hipRight.X = (firstNewFrame.HipRight.X + secondNewFrame.HipRight.X) / 2; hipRight.Y = (firstNewFrame.HipRight.Y + secondNewFrame.HipRight.Y) / 2; hipRight.Z = (firstNewFrame.HipRight.Z + secondNewFrame.HipRight.Z) / 2;
                    fourthFrame.Head = head; fourthFrame.HandLeft = handLeft; fourthFrame.HandRight = handLeft;
                    fourthFrame.ShoulderLeft = shoulderLeft; fourthFrame.ShoulderRight = shoulderRight;
                    fourthFrame.HipLeft = hipLeft; fourthFrame.HipRight = hipRight;
                    fourthFrame.FrameNo = 2;
                    #endregion
                }
                else
                {
                    fourthFrame = testingGesture.GestureFrames[middleFrame.FrameNo + (lastLength / 2)];
                }
            }
            //allInputFrame.Add(firstFrame);
            allInputFrame.Add(secondFrame);
            allInputFrame.Add(middleFrame);
            allInputFrame.Add(fourthFrame);
            //allInputFrame.Add(lastFrame);
            #endregion

            #region CreateinputArray
            double[] allInputNode = new double[63];
            int inputIndex = 0; int gestureIndex = 0;
            foreach (Model.Frame fr in allInputFrame)
            {
                for (int i = 1; i <= 7; i++)
                {
                    switch (i)
                    {
                        case 1:
                            {
                                allInputNode[inputIndex] = fr.Head.X; inputIndex++;
                                allInputNode[inputIndex] = fr.Head.Y; inputIndex++;
                                allInputNode[inputIndex] = fr.Head.Z; inputIndex++;
                                break;
                            }
                        case 2:
                            {
                                allInputNode[inputIndex] = fr.HandLeft.X; inputIndex++;
                                allInputNode[inputIndex] = fr.HandLeft.Y; inputIndex++;
                                allInputNode[inputIndex] = fr.HandLeft.Z; inputIndex++;
                                break;
                            }
                        case 3:
                            {
                                allInputNode[inputIndex] = fr.HandRight.X; inputIndex++;
                                allInputNode[inputIndex] = fr.HandRight.Y; inputIndex++;
                                allInputNode[inputIndex] = fr.HandRight.Z; inputIndex++;
                                break;
                            }
                        case 4:
                            {
                                allInputNode[inputIndex] = fr.ShoulderLeft.X; inputIndex++;
                                allInputNode[inputIndex] = fr.ShoulderLeft.Y; inputIndex++;
                                allInputNode[inputIndex] = fr.ShoulderLeft.Z; inputIndex++;
                                break;
                            }
                        case 5:
                            {
                                allInputNode[inputIndex] = fr.ShoulderRight.X; inputIndex++;
                                allInputNode[inputIndex] = fr.ShoulderRight.Y; inputIndex++;
                                allInputNode[inputIndex] = fr.ShoulderRight.Z; inputIndex++;
                                break;
                            }
                        case 6:
                            {
                                allInputNode[inputIndex] = fr.HipLeft.X; inputIndex++;
                                allInputNode[inputIndex] = fr.HipLeft.Y; inputIndex++;
                                allInputNode[inputIndex] = fr.HipLeft.Z; inputIndex++;
                                break;
                            }
                        case 7:
                            {
                                allInputNode[inputIndex] = fr.HipRight.X; inputIndex++;
                                allInputNode[inputIndex] = fr.HipRight.Y; inputIndex++;
                                allInputNode[inputIndex] = fr.HipRight.Z; inputIndex++;
                                break;
                            }
                        default:
                            break;
                    }
                }

                gestureIndex++;
            }
            #endregion

            ArrayList inputs = new ArrayList();

            foreach (long l in allInputNode)
            {
                inputs.Add(l);
            }

            ArrayList outputs = network.RunNetwork(inputs);

            return outputs;
        }

        public bool Save(String file)
        {
            NetworkSerializer ser = new NetworkSerializer();
            ser.SaveNetwork(file, network);
            return true;
        }

        public bool Load(String file)
        {
            CreateNetwork();
            NetworkSerializer ser = new NetworkSerializer();
            ser.LoadNetwork(file,ref this.network);
            return true;
        }
    }
}
